package com.rede.didiok.rank.service.impl;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.RedisConf;
import com.rede.didiok.common.constant.conf.SQLConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.conf.base.BaseSQLConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.dto.rank.RankDto;
import com.rede.didiok.common.enums.AuditStatusEnum;
import com.rede.didiok.common.enums.LevelEnum;
import com.rede.didiok.common.enums.PublishEnum;
import com.rede.didiok.common.enums.StatusEnum;
import com.rede.didiok.common.feign.FileFeignClient;
import com.rede.didiok.common.utils.JsonUtils;
import com.rede.didiok.common.utils.RedisUtil;
import com.rede.didiok.common.utils.ResultUtil;
import com.rede.didiok.common.utils.StringUtils;
import com.rede.didiok.common.utils.business.WebUtil;
import com.rede.didiok.rank.dao.RankCategoryDao;
import com.rede.didiok.rank.dao.RankDao;
import com.rede.didiok.rank.entity.RankCategoryEntity;
import com.rede.didiok.rank.entity.RankEntity;
import com.rede.didiok.rank.entity.RankMemberEntity;
import com.rede.didiok.rank.service.MemberGradeService;
import com.rede.didiok.rank.service.RankCategoryService;
import com.rede.didiok.rank.service.RankMemberService;
import com.rede.didiok.rank.service.RankService;
import com.rede.didiok.rank.vo.RankVo;


@Service("rankService")
public class RankServiceImpl extends ServiceImpl<RankDao, RankEntity> implements RankService {

    @Resource
    private RankDao rankDao;
    @Resource
    private RankCategoryDao rankCategoryDao;
    @Resource
    private FileFeignClient fileFeignClient;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private WebUtil webUtil;

    @Autowired
    private MemberGradeService memberGradeService;
    @Autowired
    private RankMemberService rankMemberService;
    @Autowired
    private RankCategoryService rankCategoryService;


    /***************************** admin:start **************************/
    // region  didiok-admin

    /**
     * 获取每个榜单分类下的榜单数目
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> getRankCountByCategory() {
        // 从Redis中获取榜单分类下包含的榜单数量
        String jsonArrayList = redisUtil.get(RedisConf.DASHBOARD + Constants.SYMBOL_COLON + RedisConf.RANK_COUNT_BY_CATEGORY);
        if (StringUtils.isNotEmpty(jsonArrayList)) {
            ArrayList jsonList = JsonUtils.jsonArrayToArrayList(jsonArrayList);
            return jsonList;
        }
        List<Map<String, Object>> rankCountByCategoryMap = rankDao.getRankCountByCategory();
        Map<String, Integer> categoryMap = new HashMap<>();
        for (Map<String, Object> item : rankCountByCategoryMap) {

            String catUid = String.valueOf(item.get(SQLConf.CAT_UID));
            // java.lang.Number是Integer,Long的父类
            Number num = (Number) item.get(SysConf.COUNT);
            Integer count = 0;
            if (num != null) {
                count = num.intValue();
            }
            categoryMap.put(catUid, count);
        }

        //把查询到的BlogSort放到Map中
        Set<String> blogSortUids = categoryMap.keySet();
        Collection<RankCategoryEntity> categoryCollection = new ArrayList<>();

        if (blogSortUids.size() > 0) {
            categoryCollection = rankCategoryDao.selectBatchIds(blogSortUids);
        }

        Map<String, String> categoryEntityMap = new HashMap<>();
        for (RankCategoryEntity category : categoryCollection) {
            if (StringUtils.isNotEmpty(category.getCatName())) {
                categoryEntityMap.put(category.getUid(), category.getCatName());
            }
        }

        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
        for (Map.Entry<String, Integer> entry : categoryMap.entrySet()) {

            String catUid = entry.getKey();

            if (categoryEntityMap.get(catUid) != null) {
                String catName = categoryEntityMap.get(catUid);
                Integer count = entry.getValue();
                Map<String, Object> itemResultMap = new HashMap<>();
                itemResultMap.put(SysConf.CAT_UID, catUid);
                itemResultMap.put(SysConf.NAME, catName);
                itemResultMap.put(SysConf.VALUE, count);
                resultList.add(itemResultMap);
            }
        }
        // 将 每个分类下文章数目 存入到Redis【过期时间2小时】
        if (resultList.size() > 0) {
            redisUtil.setEx(RedisConf.DASHBOARD + Constants.SYMBOL_COLON + RedisConf.RANK_COUNT_BY_CATEGORY, JsonUtils.objectToJson(resultList), 2, TimeUnit.HOURS);
        }
        return resultList;
    }

    @Override
    public IPage<RankEntity> getPageList(RankDto rankDto) {
        QueryWrapper<RankEntity> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(rankDto.getKeyword()) && !StringUtils.isEmpty(rankDto.getKeyword())) {
            queryWrapper.like(SQLConf.CONTENT, rankDto.getKeyword().trim());
        }

        Page<RankEntity> page = new Page<>();
        page.setCurrent(rankDto.getCurrentPage());
        page.setSize(rankDto.getPageSize());
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        if (StringUtils.isNotEmpty(rankDto.getOrderByAscColumn())) {
            // 将驼峰转换成下划线
            String column = StringUtils.underLine(new StringBuffer(rankDto.getOrderByAscColumn())).toString();
            queryWrapper.orderByAsc(column);
        } else if (StringUtils.isNotEmpty(rankDto.getOrderByDescColumn())) {
            // 将驼峰转换成下划线
            String column = StringUtils.underLine(new StringBuffer(rankDto.getOrderByDescColumn())).toString();
            queryWrapper.orderByDesc(column);
        } else {
            queryWrapper.orderByDesc(SQLConf.SORT);
        }
        IPage<RankEntity> pageList = this.page(page, queryWrapper);
        return pageList;
    }

    @Override
    public String addRank(RankDto rankDto) {
        QueryWrapper<RankEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.RANK_NAME, rankDto.getRankName());
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        RankEntity tempRank = this.getOne(queryWrapper);
        if (tempRank != null) {
            return ResultUtil.errorWithMessage(MessageConf.ENTITY_EXIST);
        }
        RankEntity rank = new RankEntity();
        rank.setRankName(rankDto.getRankName());
        rank.setContent(rankDto.getContent());
        rank.setMemberCount(0);
        rank.setStatus(StatusEnum.ENABLE);
        rank.setSort(rankDto.getSort());
        rank.insert();
        // 删除Redis中的  Rank
        deleteRedisRankList();
        return ResultUtil.successWithMessage(MessageConf.INSERT_SUCCESS);
    }

    @Override
    public String editRank(RankDto rankDto) {
        RankEntity rank = this.getById(rankDto.getUid());

        if (rank != null && !rank.getRankName().equals(rankDto.getRankName())) {
            QueryWrapper<RankEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(SQLConf.RANK_NAME, rankDto.getRankName());
            queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
            RankEntity tempRank = this.getOne(queryWrapper);
            if (tempRank != null) {
                return ResultUtil.errorWithMessage(MessageConf.ENTITY_EXIST);
            }
        }

        rank.setContent(rankDto.getContent());
        rank.setRankName(rankDto.getRankName());
        rank.setStatus(StatusEnum.ENABLE);
        rank.setSort(rankDto.getSort());
        rank.updateById();
        // 删除和标签相关的博客缓存
        this.deleteRedisByRank();
        // 删除Redis中的BLOG_TAG
        deleteRedisRankList();
        return ResultUtil.successWithMessage(MessageConf.UPDATE_SUCCESS);
    }

    @Override
    public String deleteBatchRank(List<RankDto> rankVOList) {
        if (rankVOList.size() <= 0) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }
        List<String> uids = new ArrayList<>();
        rankVOList.forEach(item -> {
            uids.add(item.getUid());
        });

        // 判断要删除的分类，是否有博客
        QueryWrapper<RankMemberEntity> blogQueryWrapper = new QueryWrapper<>();
        blogQueryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        blogQueryWrapper.in(SQLConf.RANK_UID, uids);
        Integer blogCount = rankMemberService.count(blogQueryWrapper);
        if (blogCount > 0) {
            return ResultUtil.errorWithMessage(MessageConf.MEMBER_UNDER_THIS_RANK);
        }

        Collection<RankEntity> rankList = this.listByIds(uids);

        rankList.forEach(item -> {
            item.setStatus(StatusEnum.DISABLED);
        });

        Boolean save = this.updateBatchById(rankList);
        // 删除和标签相关的博客缓存
        this.deleteRedisByRank();
        // 删除Redis中的BLOG_TAG
        deleteRedisRankList();
        if (save) {
            return ResultUtil.successWithMessage(MessageConf.DELETE_SUCCESS);
        } else {
            return ResultUtil.errorWithMessage(MessageConf.DELETE_FAIL);
        }
    }

    @Override
    public String stickRank(RankDto rankDto) {
        RankEntity rank = this.getById(rankDto.getUid());

        //查找出最大的那一个
        QueryWrapper<RankEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc(SQLConf.SORT);
        Page<RankEntity> page = new Page<>();
        page.setCurrent(0);
        page.setSize(1);
        IPage<RankEntity> pageList = this.page(page, queryWrapper);
        List<RankEntity> list = pageList.getRecords();
        RankEntity maxRank = list.get(0);

        if (StringUtils.isEmpty(maxRank.getUid())) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }
        if (maxRank.getUid().equals(rank.getUid())) {
            return ResultUtil.errorWithMessage(MessageConf.THIS_TAG_IS_TOP);
        }

        Integer sortCount = maxRank.getSort() + 1;

        rank.setSort(sortCount);
        rank.updateById();
        // 删除Redis中的BLOG_TAG
        deleteRedisRankList();
        return ResultUtil.successWithMessage(MessageConf.OPERATION_SUCCESS);
    }

    @Override
    public String rankSortByMemberCount() {
        // 定义Map   key：rankUid,  value: 引用量
        Map<String, Integer> map = new HashMap<>();
        QueryWrapper<RankEntity> rankQueryWrapper = new QueryWrapper<>();
        rankQueryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        List<RankEntity> rankList = this.list(rankQueryWrapper);
        // 初始化所有标签的引用量
        rankList.forEach(item -> {
            map.put(item.getUid(), 0);
        });

        QueryWrapper<RankMemberEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.eq(SQLConf.IS_PUBLISH, PublishEnum.PUBLISH);
        // 过滤content字段
        queryWrapper.select(RankMemberEntity.class, i -> !i.getProperty().equals(SQLConf.CONTENT));
        List<RankMemberEntity> blogList = rankMemberService.list(queryWrapper);

        blogList.forEach(item -> {
            String rankUids = item.getRankUid();
            List<String> rankUidList = StringUtils.changeStringToString(rankUids, SysConf.FILE_SEGMENTATION);
            for (String rankUid : rankUidList) {
                if (map.get(rankUid) != null) {
                    Integer count = map.get(rankUid) + 1;
                    map.put(rankUid, count);
                } else {
                    map.put(rankUid, 0);
                }
            }
        });

        rankList.forEach(item -> {
            item.setSort(map.get(item.getUid()));
        });
        this.updateBatchById(rankList);
        // 删除Redis中的BLOG_TAG
        deleteRedisRankList();
        return ResultUtil.successWithMessage(MessageConf.OPERATION_SUCCESS);
    }


    // endregion
    /***************************** admin:end **************************/



    /***************************** web:start **************************/
    // region didiok-web

    /**
     * 获取热门榜单
     *
     * @param hotRankCount
     * @return
     */
    @Override
    public List<RankEntity> getHotRank(Integer hotRankCount) {
        QueryWrapper<RankEntity> queryWrapper = new QueryWrapper<>();
        Page<RankEntity> page = new Page<>();
        page.setCurrent(1);
        page.setSize(hotRankCount);
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.orderByDesc(SQLConf.SORT);
//        queryWrapper.orderByDesc(SQLConf.CLICK_COUNT);
        IPage<RankEntity> pageList = this.page(page, queryWrapper);
        return pageList.getRecords();
    }

    /**
     * 通过 catUid 获取榜单列表
     *
     * @param catUid
     * @param currentPage
     * @param pageSize
     * @return
     */
    @Override
    public IPage<RankEntity> getListByCatUid(String catUid, Long currentPage, Long pageSize) {
        //分页
        Page<RankEntity> page = new Page<>();
        page.setCurrent(currentPage);
        page.setSize(pageSize);
        QueryWrapper<RankEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.orderByDesc(SQLConf.CREATE_TIME);
        queryWrapper.eq(BaseSQLConf.IS_PUBLISH, PublishEnum.PUBLISH);
        queryWrapper.eq(SQLConf.AUDIT_STATUS, AuditStatusEnum.AGREE);
        queryWrapper.eq(SQLConf.CAT_UID, catUid);

        //因为首页并不需要显示内容，所以需要排除掉内容字段
//        queryWrapper.select(Blog.class, i -> !i.getProperty().equals(SQLConf.CONTENT));
        IPage<RankEntity> pageList = this.page(page, queryWrapper);

        //给博客增加标签和分类
        List<RankEntity> list = this.setCatAndPictureByRankList(pageList.getRecords());
        pageList.setRecords(list);
        return pageList;
    }

    @Override
    public List<RankEntity> getList() {
        QueryWrapper<RankEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.orderByDesc(SQLConf.SORT);
        List<RankEntity> rankList = this.list(queryWrapper);
        return rankList;
    }

    // endregion
    /***************************** web:end **************************/

    @Override
    public void deleteRedisByRankCategory() {
        // 删除Redis中榜单分类下的榜单数量
        redisUtil.delete(RedisConf.DASHBOARD + Constants.SYMBOL_COLON + RedisConf.RANK_COUNT_BY_CATEGORY);
        // 删除榜单相关缓存
        deleteRedisByRank();
    }

    @Override
    public void deleteRedisByRank() {
        // 删除Redis中榜单下的榜单成员数量
        redisUtil.delete(RedisConf.DASHBOARD + Constants.SYMBOL_COLON + RedisConf.RANK_MEMBER_COUNT_BY_RANK);

        // 删除榜单相关缓存
        redisUtil.delete(RedisConf.NEW_RANK);
        redisUtil.delete(RedisConf.HOT_RANK);
        redisUtil.delete(RedisConf.RANK_LEVEL + Constants.SYMBOL_COLON + LevelEnum.FIRST);
        redisUtil.delete(RedisConf.RANK_LEVEL + Constants.SYMBOL_COLON + LevelEnum.SECOND);
        redisUtil.delete(RedisConf.RANK_LEVEL + Constants.SYMBOL_COLON + LevelEnum.THIRD);
        redisUtil.delete(RedisConf.RANK_LEVEL + Constants.SYMBOL_COLON + LevelEnum.FOURTH);

        // 删除榜单下的榜单成员相关缓存
        rankMemberService.deleteRedisByRankMember();
    }

    /**
     * 修改榜单的显示状态
     * @param rank
     */
    @Override
    public void updateDeleteStatusByUid(RankEntity rank) {
        rankDao.updateDeleteStatusByUid(rank.getUid(), rank.getStatus());

    }

    /**
     * 根据分类获取榜单列表
     *
     * @param catUid
     * @return
     */
    @Override
    public List<RankVo> listRankByCategory(String catUid) {
        List<RankEntity> rankEntityList = baseMapper.selectList(new QueryWrapper<RankEntity>().eq("cat_uid", catUid));
        List<RankVo> collect = rankEntityList.stream().map(item -> {
            RankVo rankVo = new RankVo();
            rankVo.setUid(item.getUid());
            rankVo.setRankName(item.getRankName());
            return rankVo;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 批量：根据榜单id列表，获取榜单信息
     *
     * @param rankUids
     * @return
     */
    @Override
    public List<RankEntity> getRanksByIds(List<String> rankUids) {
        return baseMapper.selectList(new QueryWrapper<RankEntity>().in("uid",rankUids));
    }

    /**
     * 删除Redis中的rank列表
     */
    private void deleteRedisRankList() {
        // 删除Redis中的rank列表
        Set<String> keys = redisUtil.keys(RedisConf.RANK + Constants.SYMBOL_COLON + "*");
        redisUtil.delete(keys);
    }

    private List<RankEntity> setCatAndPictureByRankList(List<RankEntity> list) {

        List<String> catUids = new ArrayList<>();
        Set<String> fileUidSet = new HashSet<>();

        list.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getFileUid())) {
                fileUidSet.add(item.getFileUid());
            }
            if (StringUtils.isNotEmpty(item.getCatUid())) {
                catUids.add(item.getCatUid());
            }

        });

        String pictureList = null;
        StringBuffer fileUids = new StringBuffer();
        List<Map<String, Object>> picList = new ArrayList<>();
        // feign分页查询图片数据
        if (fileUidSet.size() > 0) {
            int count = 1;
            for (String fileUid : fileUidSet) {
                fileUids.append(fileUid + ",");
                System.out.println(count % 10);
                if (count % 10 == 0) {
                    pictureList = fileFeignClient.getPicture(fileUids.toString(), ",");
                    List<Map<String, Object>> tempPicList = webUtil.getPictureMap(pictureList);
                    picList.addAll(tempPicList);
                    fileUids = new StringBuffer();
                }
                count++;
            }
            // 判断是否存在图片需要获取
            if (fileUids.length() >= Constants.NUM_32) {
                pictureList = fileFeignClient.getPicture(fileUids.toString(), Constants.SYMBOL_COMMA);
                List<Map<String, Object>> tempPicList = webUtil.getPictureMap(pictureList);
                picList.addAll(tempPicList);
            }
        }

        Collection<RankCategoryEntity> catList = new ArrayList<>();

        if (catUids.size() > 0) {
            catList = rankCategoryService.listByIds(catUids);
        }

        Map<String, RankCategoryEntity> catMap = new HashMap<>();
        Map<String, String> pictureMap = new HashMap<>();

        catList.forEach(item -> {
            catMap.put(item.getUid(), item);
        });

        picList.forEach(item -> {
            pictureMap.put(item.get(SysConf.UID).toString(), item.get(SysConf.URL).toString());
        });

        for (RankEntity item : list) {
            //设置分类
            if (StringUtils.isNotEmpty(item.getCatUid())) {

                item.setCategory(catMap.get(item.getCatUid()));
                if (catMap.get(item.getCatUid()) != null) {
                    item.setCatName(catMap.get(item.getCatUid()).getCatName());
                }
            }

            //获取图片
            if (StringUtils.isNotEmpty(item.getFileUid())) {
                List<String> pictureUidsTemp = StringUtils.changeStringToString(item.getFileUid(), Constants.SYMBOL_COMMA);
                List<String> pictureListTemp = new ArrayList<String>();

                pictureUidsTemp.forEach(picture -> {
                    pictureListTemp.add(pictureMap.get(picture));
                });
                item.setPhotoList(pictureListTemp);
                // 只设置一张标题图
                if (pictureListTemp.size() > 0) {
                    item.setPhotoUrl(pictureListTemp.get(0));
                } else {
                    item.setPhotoUrl("");
                }
            }
        }
        return list;
    }

}